package com.lagou.controller;

import com.lagou.common.pojo.FlashSale;
import com.lagou.common.pojo.Order;
import com.lagou.common.service.FlashSaleService;
import com.lagou.common.service.OrderService;
import com.lagou.entity.RestResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

@RestController
@RequestMapping("/api/flashsale")
public class FlashSaleController {


    /**
     * redis分布式锁名称
     */
    private String lockKey = "lock";

    /**
     * 秒杀开始时间
     */
    private Date flashSaleStartTime;

    /**
     * 秒杀数量
     */
    private int totalSaleNum = 100;

    private int productPrice;

    /**
     * 商品名称
     */
    private String product = "LagouPhone";

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;


    @Autowired
    private FlashSaleService flashSaleService;

    @Autowired
    private OrderService orderService;



    /**
     * 秒杀初始化
     * @return
     */
    @GetMapping("/init")
    public String init() {
        List<FlashSale> all = flashSaleService.findAll();
        FlashSale flashSale = all.get(0);

        System.out.println(flashSale);

        flashSaleStartTime = flashSale.getStartTime();
        redisTemplate.boundValueOps(lockKey).set("0");
        totalSaleNum = flashSale.getStock();
        product = flashSale.getName();
        productPrice = flashSale.getPrice();

        return "init ok";
    }


    private void sendCreateOrderMessage(String userId) {
        System.out.println(userId + " : 生产订单消息到消息队列");

        Order order = new Order();
        order.setName(product);
        order.setAmount(productPrice);
        order.setStatus("paying");
        order.setOrderTime(new Date());
        order.setUserId(userId);



        rocketMQTemplate.convertAndSend("order-mq", order);
    }

    @GetMapping("/info")
    public FlashSale info() {

        FlashSale flashSale = new FlashSale();
        flashSale.setName(product);
        flashSale.setStock(totalSaleNum - Integer.valueOf((String)redisTemplate.opsForValue().get(lockKey)));
        flashSale.setStartTime(flashSaleStartTime);
        flashSale.setPrice(productPrice);

        return flashSale;
    }

    @GetMapping("/orderList")
    public List<Order> orderList(@RequestParam String userId) {
        return orderService.findAllByUserId(userId);
    }

    /**
     * 秒杀
     * @param userId
     * @return
     */
    @GetMapping("/buy")
    public RestResult buy(@RequestParam String userId) {

        if ((new Date()).before(flashSaleStartTime)) {
            RestResult restResult = new RestResult();
            restResult.setStatus(3);
            restResult.setMessage("秒杀还未开始");

            return restResult;
        }

        RestResult result = (RestResult)redisTemplate.execute(new SessionCallback<RestResult>() {
            public RestResult execute(RedisOperations operations) throws DataAccessException {

                RestResult restResult = new RestResult();
                operations.watch(lockKey);

                String value = (String) operations.opsForValue().get(lockKey);
                Integer currSaleNum = Integer.valueOf(value);

                // 仍然有剩余库存，继续秒杀
                if (currSaleNum < totalSaleNum) {

                    operations.multi();
                    operations.boundValueOps(lockKey).increment();
                    List exec = operations.exec();

                    if (exec != null && exec.size() > 0) {
                        restResult.setStatus(0);
                        restResult.setMessage("秒杀成功！");
                        sendCreateOrderMessage(userId);
                    } else {
                        restResult.setStatus(1);
                        restResult.setMessage("秒杀失败！");
                    }

                } else {    // 没有库存，秒杀结束
                    operations.unwatch();
                    restResult.setStatus(2);
                    restResult.setMessage("秒杀结束！");
                }

                return restResult;
            }
        });


        return result;
    }

    /**
     * 支付
     * @param orderId
     * @return
     */
    @GetMapping("/pay")
    public int pay(@RequestParam Long orderId) {

        return orderService.payOrder(orderId);

    }

}
